package com.pactera.asmp.server.service;

import com.pactera.asmp.server.common.constants.Constants;
import com.pactera.asmp.server.common.constants.ResultCode;
import com.pactera.asmp.server.common.exception.CustomException;
import com.pactera.asmp.server.dao.DeviceInfoMapper;
import com.pactera.asmp.server.dao.TProjectDeviceDbcMapper;
import com.pactera.asmp.server.entity.ProjectDeviceBindDto;
import com.pactera.asmp.server.entity.ProjectDeviceDbcBindDto;
import com.pactera.asmp.server.entity.ResponseResult;
import com.pactera.asmp.server.pojo.DeviceInfo;
import com.pactera.asmp.server.pojo.DeviceProjectDbcVo;
import com.pactera.asmp.server.pojo.ProjectDbcInfo;
import com.pactera.asmp.server.pojo.ProjectDeviceDbc;
import com.pactera.asmp.server.pojo.TProjectDeviceDbc;
import com.pactera.asmp.server.pojo.TProjectDeviceDbcDetail;
import com.pactera.asmp.server.pojo.TProjectDeviceDbcExample;
import com.pactera.asmp.server.pojo.User;
import com.pactera.asmp.server.utils.AssertUtil;

import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

/**
 * @ProjectName: asmp-server
 * @Package com.pactera.asmp.server.service
 * @ClassName: ProjectDeviceDbcServiceImpl
 * @Description: ProjectDeviceDbcServiceImpl
 * @Date 2020/07/24 16:34
 * @Author lvzhiqiang
 * @Version 1.0
 */
@Service
public class ProjectDeviceDbcServiceImpl implements IProjectDeviceDbcService {
    @Resource
    private TProjectDeviceDbcMapper projectDeviceDbcMapper;

    @Resource
    private DeviceInfoMapper deviceInfoMapper;

    @Override
    public int insert(List<TProjectDeviceDbc> projectDeviceDbcs) {
        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (null == currUser) {
            throw new CustomException(ResultCode.PERMISSION_EXPIRE);
        }
        for (TProjectDeviceDbc projectDeviceDbc : projectDeviceDbcs) {
            // 验证参数
            this.checkParam(projectDeviceDbc);

            projectDeviceDbc.setCreateUserId(currUser.getId());
            projectDeviceDbc.setUpdateUserId(currUser.getId());
            projectDeviceDbc.setCreateTime(LocalDateTime.now());
            projectDeviceDbc.setUpdateTime(LocalDateTime.now());
        }
        return projectDeviceDbcMapper.batchInsert(projectDeviceDbcs);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDbc(ProjectDeviceDbcBindDto projectDeviceDbcBindDto) {
        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (null == currUser) {
            throw new CustomException(ResultCode.PERMISSION_EXPIRE);
        }
        int count = 0;
        Integer projectId = projectDeviceDbcBindDto.getProjectId();
        List<TProjectDeviceDbc> projectDeviceDbcs = projectDeviceDbcBindDto.getList();
        for (TProjectDeviceDbc projectDeviceDbc : projectDeviceDbcs) {
            if (null == projectDeviceDbc.getDbcId() || 0 == projectDeviceDbc.getDbcId()) {
                throw new CustomException(ResultCode.PARAM_IS_BLANK);
            }
            projectDeviceDbc.setProjectId(projectId);
            this.checkParam(projectDeviceDbc);
            projectDeviceDbc.setUpdateUserId(currUser.getId());
            projectDeviceDbc.setUpdateTime(LocalDateTime.now());

            count += projectDeviceDbcMapper.updateByPrimaryKeySelective(projectDeviceDbc);
        }
        return count;
    }

    @Override
    public int batchDelete(List<TProjectDeviceDbc> projectDeviceDbcs) {
        TProjectDeviceDbcExample example = new TProjectDeviceDbcExample();
        for (TProjectDeviceDbc projectDeviceDbc : projectDeviceDbcs) {
            this.checkParam(projectDeviceDbc);
            example.or()
                    .andProjectIdEqualTo(projectDeviceDbc.getProjectId())
                    .andDeviceIdEqualTo(projectDeviceDbc.getDeviceId());
        }
        return projectDeviceDbcMapper.deleteByExample(example);
    }

    @Override
    public List<TProjectDeviceDbc> selective(Integer projectId, Integer deviceId) {
        TProjectDeviceDbcExample example = new TProjectDeviceDbcExample();
        TProjectDeviceDbcExample.Criteria criteria = example.createCriteria();

        if (null != projectId && 0 != projectId) {
            criteria.andProjectIdEqualTo(projectId);
        }
        if (null != deviceId && 0 != deviceId) {
            criteria.andDeviceIdEqualTo(deviceId);
        }
        return projectDeviceDbcMapper.selectByExample(example);
    }

    @Override
    public List<Map> queryProjectAndDbcByDuid(String duid) {
        return projectDeviceDbcMapper.queryProjectAndDbcByDuid(duid);
    }

    /**
     * 验证必传参数
     *
     * @param projectDeviceDbc
     */
    private void checkParam(TProjectDeviceDbc projectDeviceDbc) {
        Integer projectId = projectDeviceDbc.getProjectId();
        Integer deviceId = projectDeviceDbc.getDeviceId();
        if (null == projectId || 0 == projectId
                || null == deviceId || 0 == deviceId) {
            throw new CustomException(ResultCode.PARAM_IS_BLANK);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchBind(ProjectDeviceBindDto projectDeviceBindDto) {
        List<TProjectDeviceDbc> projectDeviceDbcs = this.selective(projectDeviceBindDto.getProjectId(), null);
        List<Integer> deviceList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(projectDeviceDbcs)) {
            for (TProjectDeviceDbc projectDeviceDbc : projectDeviceDbcs) {
                deviceList.add(projectDeviceDbc.getDeviceId());
            }
        }

        List<TProjectDeviceDbc> newProjectDeviceDbcs = new ArrayList<>();
        List<Integer> deviceIds = projectDeviceBindDto.getDeviceIds();
        if (CollectionUtils.isEmpty(deviceIds)) {
            deviceIds = new ArrayList<>();
        }
        for (Integer deviceId : deviceIds) {
            if (!deviceList.contains(deviceId)) {
                TProjectDeviceDbc projectDeviceDbc = new TProjectDeviceDbc();
                projectDeviceDbc.setProjectId(projectDeviceBindDto.getProjectId());
                projectDeviceDbc.setDeviceId(deviceId);
                newProjectDeviceDbcs.add(projectDeviceDbc);
            } else {
                deviceList.remove(deviceId);
            }
        }

        // 批量删除
        if (!CollectionUtils.isEmpty(deviceList)) {
            // 检测解绑的设备是否正在执行任务
            List<DeviceInfo> deviceInfos = deviceInfoMapper.selectByPrimaryKeys(deviceList, 1);
            if (!CollectionUtils.isEmpty(deviceInfos)) {
                throw new CustomException(ResultCode.BUSINESS_PROJECT_DEVICE_UNBIND_FAIL);
            }

            TProjectDeviceDbcExample example = new TProjectDeviceDbcExample();
            example.createCriteria().andProjectIdEqualTo(projectDeviceBindDto.getProjectId())
                    .andDeviceIdIn(deviceList);
            projectDeviceDbcMapper.deleteByExample(example);
        }

        // 批量添加
        if (!CollectionUtils.isEmpty(newProjectDeviceDbcs)) {
            this.insert(newProjectDeviceDbcs);
        }
        return 1;
    }

    @Override
    @Transactional
    public ResponseResult deviceBind(DeviceProjectDbcVo deviceProjectDbcVo) {
        AssertUtil.notNull(deviceProjectDbcVo, "参数异常");
        AssertUtil.notNull(deviceProjectDbcVo.getDeviceId(), "设备ID不允许为空");

        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (currUser == null) throw new CustomException(ResultCode.PERMISSION_EXPIRE);
        LocalDateTime now = LocalDateTime.now();

        int count =0 ;

        // 1. 修改昵称
        if(!StringUtils.isEmpty(deviceProjectDbcVo.getNickName())) {
            AssertUtil.isTrue(deviceProjectDbcVo.getNickName().matches(Constants.REGEXP_FIRST_LAST_NOT_SPACE),"昵称格式不正确");
            DeviceInfo deviceInfo = new DeviceInfo();
            deviceInfo.setId(deviceProjectDbcVo.getDeviceId());
            deviceInfo.setNickName(deviceProjectDbcVo.getNickName());
            count = deviceInfoMapper.updateNickName(deviceInfo);
            if (count < 1) throw new CustomException(ResultCode.DATA_IS_WRONG);
        }else{
            DeviceInfo deviceInfo = new DeviceInfo();
            deviceInfo.setId(deviceProjectDbcVo.getDeviceId());
            deviceInfo.setNickName("");
            count = deviceInfoMapper.updateNickName(deviceInfo);
            if (count < 1) throw new CustomException(ResultCode.DATA_IS_WRONG);
        }
        // 2. 读取当前设备的绑定关系
        List<TProjectDeviceDbc> list = this.selective(null, deviceProjectDbcVo.getDeviceId());

        // 3. 配置增、删、改的关系
        if (!CollectionUtils.isEmpty(list) && CollectionUtils.isEmpty(deviceProjectDbcVo.getProjectDbcInfos())) {
            // db有数据，参数无数据，表示删除清空
            this.projectDeviceDbcMapper.clearByDeviceId(deviceProjectDbcVo.getDeviceId());
            if (count < 1) throw new CustomException(ResultCode.DATA_IS_WRONG);
        }
        else if (CollectionUtils.isEmpty(list) && !CollectionUtils.isEmpty(deviceProjectDbcVo.getProjectDbcInfos())) {
            // db无数据，参数有数据，表示全部新增
            List<TProjectDeviceDbc> insertList = new ArrayList<>();
            for(ProjectDbcInfo projectDbcInfo :deviceProjectDbcVo.getProjectDbcInfos()){
                TProjectDeviceDbc projectDeviceDbc = new TProjectDeviceDbc();
                insertList.add(projectDeviceDbc);
                projectDeviceDbc.setUpdateTime(now);
                projectDeviceDbc.setUpdateUserId(currUser.getId());
                projectDeviceDbc.setCreateTime(now);
                projectDeviceDbc.setCreateUserId(currUser.getId());
                projectDeviceDbc.setProjectId(projectDbcInfo.getProjectId());
                projectDeviceDbc.setDeviceId(deviceProjectDbcVo.getDeviceId());
                projectDeviceDbc.setDbcId(projectDbcInfo.getDbcId());
            }
            if(!CollectionUtils.isEmpty(insertList)){
                count = projectDeviceDbcMapper.batchInsert(insertList);
                if (count < 1) throw new CustomException(ResultCode.DATA_IS_WRONG);
            }
        }
        else if (!CollectionUtils.isEmpty(list) && !CollectionUtils.isEmpty(deviceProjectDbcVo.getProjectDbcInfos())){
            // 比较判断
            boolean exist;
            for(TProjectDeviceDbc dbItem : list){
                // 删除和修改
                exist = false;
                for(ProjectDbcInfo paramItem : deviceProjectDbcVo.getProjectDbcInfos()){
                    if(dbItem.getProjectId().equals(paramItem.getProjectId()) && dbItem.getDeviceId().equals(deviceProjectDbcVo.getDeviceId())){
                        exist = true;
                        if(dbItem.getDbcId() == null && paramItem.getDbcId()== null ||  dbItem.getDbcId()!= null && dbItem.getDbcId().equals(paramItem.getDbcId())) continue;
                        // 修改
                        TProjectDeviceDbc updatPo = new TProjectDeviceDbc();
                        updatPo.setProjectId(paramItem.getProjectId());
                        updatPo.setDeviceId(deviceProjectDbcVo.getDeviceId());
                        updatPo.setDbcId(paramItem.getDbcId());
                        updatPo.setUpdateUserId(currUser.getId());
                        updatPo.setUpdateTime(now);
                        count = this.projectDeviceDbcMapper.updateByPrimaryKeySelective(updatPo);
                        if (count < 1) throw new CustomException(ResultCode.DATA_IS_WRONG);
                        break;
                    }
                }
                if(!exist){
                    // 删除
                    TProjectDeviceDbc updatPo = new TProjectDeviceDbc();
                    updatPo.setProjectId(dbItem.getProjectId());
                    updatPo.setDeviceId(dbItem.getDeviceId());
                    count = this.projectDeviceDbcMapper.deleteByPrimaryKey(updatPo);
                    if (count < 1) throw new CustomException(ResultCode.DATA_IS_WRONG);
                }
            }
            for (ProjectDbcInfo paramItem : deviceProjectDbcVo.getProjectDbcInfos()){
                // 新增
                exist = false;
                for(TProjectDeviceDbc dbItem : list){
                    if(dbItem.getProjectId().equals(paramItem.getProjectId()) && dbItem.getDeviceId().equals(deviceProjectDbcVo.getDeviceId())){
                        exist = true;
                        break;
                    }
                }
                if(!exist){
                    TProjectDeviceDbc newPo = new TProjectDeviceDbc();
                    newPo.setProjectId(paramItem.getProjectId());
                    newPo.setDeviceId(deviceProjectDbcVo.getDeviceId());
                    newPo.setDbcId(paramItem.getDbcId());
                    newPo.setCreateUserId(currUser.getId());
                    newPo.setCreateTime(now);
                    newPo.setUpdateUserId(currUser.getId());
                    newPo.setUpdateTime(now);
                    count = this.projectDeviceDbcMapper.insert(newPo);
                    if (count < 1) throw new CustomException(ResultCode.DATA_IS_WRONG);
                }
            }
        }
        return ResponseResult.defaultSuccess(null);
    }

    @Override
    public List<TProjectDeviceDbcDetail> selective2(Integer projectId, Integer deviceId,String duid) {
        if(deviceId == null && StringUtils.isEmpty(duid)) throw  new CustomException(ResultCode.PARAM_NOT_COMPLETE);
        return projectDeviceDbcMapper.selective2(projectId, deviceId,duid);
    }

    @Override
    public List<ProjectDeviceDbc> getProjectDeviceDbcsByDeviceId(Integer deviceId) {
        AssertUtil.notNull(deviceId,"设备ID不允许为空");
        return projectDeviceDbcMapper.getProjectDeviceDbcsByDeviceId(deviceId);
    }
}
